#include "preprocessing.hpp"

std::vector<Rect> getCandidateBox(Mat src)
{
    Mat gray;
    cvtColor(src, gray, CV_BGR2GRAY);
     // morphological gradient
    Mat grad;
    Mat morphKernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
    morphologyEx(gray, grad, MORPH_GRADIENT, morphKernel);
    // binarize
    Mat bw;
    threshold(grad, bw, 0.0, 255.0, THRESH_BINARY | THRESH_OTSU);
    
    // connect horizontally oriented regions
    Mat connected;
    morphKernel = getStructuringElement(MORPH_RECT, Size(10, 7));
    morphologyEx(bw, connected, MORPH_CLOSE, morphKernel);
    // find contours
    Mat mask = Mat::zeros(bw.size(), CV_8UC1);
    vector< vector<Point> > contours;
    vector<Vec4i> hierarchy;
    std::vector<Rect> candidateBoxes;
    findContours(connected, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
    // filter contours
    for(int idx = 0; idx >= 0; idx = hierarchy[idx][0])
    {
        Rect rect = boundingRect(contours[idx]);
        Mat maskROI(mask, rect);
        maskROI = Scalar(0, 0, 0);
        // fill the contour
        drawContours(mask, contours, idx, Scalar(255, 255, 255), CV_FILLED);
        // ratio of non-zero pixels in the filled region
        double r = (double)countNonZero(maskROI)/(rect.width*rect.height);

        if (r > .45 /* assume at least 45% of the area is filled if it contains text */
            && 
            (rect.height > 8 && rect.width > 8) /* constraints on region size */
            /* these two conditions alone are not very robust. better to use something 
            like the number of significant peaks in a horizontal projection as a third condition */
            )
        {
            //rectangle(rgb, rect, Scalar(0, 255, 0), 2);
            candidateBoxes.push_back(rect);
        }
    }
    return candidateBoxes;	
}

void boxImageProcessing(Mat &src)
{
//   cvtColor(src, src, CV_BGR2GRAY);
//      pyrUp(src,src);
 //     normalize(src, src, 0, 255, NORM_MINMAX); 
//   //equalizeHist( src, src );
//   //threshold(src, src, 0, 255, CV_THRESH_OTSU);
//   adaptiveThreshold(src,src,255,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY,3,0);
      resize(src,src,Size(2*src.cols,2*src.rows),CV_INTER_LINEAR);
      //normalize(src, src, 0, 255, NORM_MINMAX); 
      imwrite("zzyywwsrc.jpg",src);
      system("./textcleaner -g -e stretch -f 25 -o 5 -s 1 zzyywwsrc.jpg zzyywwcvt.jpg");
      src=imread("zzyywwcvt.jpg");
      cvtColor(src, src, CV_BGR2GRAY);
       Mat element = getStructuringElement( MORPH_CROSS,
                                       Size( 1, 1 ),
                                       Point( -1, -1 ) );
       
       //erode( src, src,element);
       dilate( src, src, element );
}

void tesserInit(tesseract::TessBaseAPI &tess)
{
    
    if (tess.Init("D:\Program Files (x86)\Tesseract-OCR\tessdata", "eng"))
    {
        std::cout << "OCRTesseract: Could not initialize tesseract." << std::endl;
        return;
    }

    // setup
    //tess.SetPageSegMode(tesseract::PageSegMode::PSM_AUTO);
    //tess.SetVariable("save_best_choices", "T");
    /* tess.SetVariable("language_model_penalty_non_freq_dict_word", "0.9");
    tess.SetVariable("chop_enable", "T");
    tess.SetVariable("user_words_suffix", "至 经营范围 名称 类型 住所 法定代表人 注册资本 成立日期 营业期限 有限公司 注册号 中华人民共和国国家工商行政管理总局监制 营 0 1 2 3 4 5 6 7 8 9");
    tess.SetVariable("language_model_penalty_non_dict_word", "0.2");
    tess.SetVariable("use_new_state_cost", "F");
    tess.SetVariable("segment_segcost_rating", "F");
    tess.SetVariable("enable_new_segsearch", "0");
    tess.SetVariable("language_model_ngram_on", "0");
    tess.SetVariable("textord_force_make_prop_words", "F");
    tess.SetVariable("edges_max_children_per_outline", "40"); */
	tess.SetPageSegMode(tesseract::PageSegMode::PSM_AUTO);
    tess.SetVariable("tessedit_char_whitelist", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
    tess.SetVariable("save_best_choices", "T");

}

static bool rectSortFun( Rect elem1, Rect elem2 )  
{  
   int y1=elem1.tl().y;
   int y2=elem2.tl().y;
   int x1=elem1.tl().x;
   int x2=elem2.tl().x;
   if(abs(y1-y2)>5) return y1<y2;
   else if(abs(y1-y2)<=5) return x1<x2;
   else return false;
}  

void sortRect(std::vector<Rect> &boxes)
{
	sort(boxes.begin(),boxes.end(),rectSortFun);
}